//
// BoundingBox.cpp for  in /home/herpec_j/Dropbox/Projets/raytracer-2016/Sources/Maths/
//
// Made by Jonathan
// Login   <ledey_l@epitech.net>
//
// Started on  Sat Sep 21 22:40:36 2013 Jonathan
// Last update Sun Sep 22 16:28:02 2013 Jonathan
//

#include		"Maths/BoundingBox.hpp"

namespace		Maths
{
  BoundingBox::BoundingBox(long double rX0, long double rX1, long double rY0, long double rY1, long double rZ0, long double rZ1) : mX0(rX0), mX1(rX1), mY0(rY0), mY1(rY1), mZ0(rZ0), mZ1(rZ1)
  {
    return;
  }

  BoundingBox::BoundingBox(Vector const &rPoint0, Vector const &rPoint1) : mX0(rPoint0[0]), mX1(rPoint1[0]), mY0(rPoint0[1]), mY1(rPoint1[1]), mZ0(rPoint0[2]), mZ1(rPoint1[2])
  {
    return;
  }

  BoundingBox::BoundingBox(BoundingBox const &rOther) : mX0(rOther.mX0), mX1(rOther.mX1), mY0(rOther.mY0), mY1(rOther.mY1), mZ0(rOther.mZ0), mZ1(rOther.mZ1)
  {
    return;
  }

  BoundingBox		&BoundingBox::operator=(BoundingBox const &rOther)
  {
    if (this != &rOther)
      {
	mX0 = rOther.mX0;
	mX1 = rOther.mX1;
	mY0 = rOther.mY0;
	mY1 = rOther.mY1;
	mZ0 = rOther.mZ0;
	mZ1 = rOther.mZ1;
      }
    return (*this);
  }

  bool			BoundingBox::HasInside(Vector const &rPoint) const
  {
    return ((rPoint[0] > mX0 && rPoint[0] < mX1)
	    && (rPoint[1] > mY0 && rPoint[1] < mY1)
	    && (rPoint[2] > mZ0 && rPoint[2] < mZ1));
  }

  bool			BoundingBox::IsHit(Ray const &rRay) const
  {
    Vector const	&origin = rRay.GetOrigin();
    Vector const	&direction = rRay.GetDirection();
    long double		a = 1.0f / direction[0];
    long double		b = 1.0f / direction[1];
    long double		c = 1.0f / direction[2];
    long double		tx_min;
    long double		ty_min;
    long double		tz_min;
    long double		tx_max;
    long double		ty_max;
    long double		tz_max;
    long double		t0;
    long double		t1;

    if (a >= 0)
      {
	tx_min = a * (mX0 - origin[0]);
	tx_max = a * (mX1 - origin[0]);
      }
    else
      {
	tx_min = a * (mX1 - origin[0]);
	tx_max = a * (mX0 - origin[0]);
      }
    if (b >= 0)
      {
	ty_min = b * (mY0 - origin[1]);
	ty_max = b * (mY1 - origin[1]);
      }
    else
      {
	ty_min = b * (mY1 - origin[1]);
	ty_max = b * (mY0 - origin[1]);
      }
    if (c >= 0)
      {
	tz_min = c * (mZ0 - origin[2]);
	tz_max = c * (mZ1 - origin[2]);
      }
    else
      {
	tz_min = c * (mZ1 - origin[2]);
	tz_max = c * (mZ0 - origin[2]);
      }
    t0 = tx_min > ty_min ? tx_min : ty_min;
    if (tz_min > t0)
      {
	t0 = tz_min;
      }
    t1 = tx_max < ty_max ? tx_max : ty_max;
    if (tz_max < t1)
      {
	t1 = tz_max;
      }
    return (t0 < t1 && t1 > EPSILON);
  }

  BoundingBox::~BoundingBox(void)
  {
    return;
  }
};
